package org.vacoor.nothing.common.codec;

import java.io.ByteArrayOutputStream;

/**
 * Base62
 * 实现来自网络, 原理:替换 base64 中 i --> ia, + --> ib, / --> ic
 *
 * @author vacoor
 */
public abstract class Base62 {
    private static char[] DIGITS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray();
    private static byte[] INV = new byte[256];

    static {
        for (int i = 0; i < DIGITS.length; i++) {
            INV[DIGITS[i]] = (byte) i;
        }
    }

    public static String encode(byte[] bytes) {
        StringBuilder buff = new StringBuilder(bytes.length * 2);
        int pos = 0;
        int val = 0;

        for (int i = 0; i < bytes.length; i++) {
            byte b = bytes[i];

            val = (val << 8) | (b & 0xFF);
            pos += 8;

            while (pos > 5) {
                char c = DIGITS[val >> (pos -= 6)];
                buff.append(c == 'i' ? "ia" : c == '+' ? "ib" : c == '/' ? "ic" : c);
                val &= ((1 << pos) - 1);
            }
        }

        if (pos > 0) {
            char c = DIGITS[val << (6 - pos)];
            buff.append(c == 'i' ? "ia" : c == '+' ? "ib" : c == '/' ? "ic" : c);
        }
        return buff.toString();
    }

    public static byte[] decode(String base62) {
        return decode(base62.toCharArray());
    }

    public static byte[] decode(char[] base62Chars) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream(base62Chars.length);
        int pos = 0;
        int val = 0;

        for (int i = 0; i < base62Chars.length; i++) {
            char c = base62Chars[i];

            if (c == 'i') {
                c = base62Chars[++i];
                c = c == 'a' ? 'i' : c == 'b' ? '+' : c == 'c' ? '/' : base62Chars[--i];
            }

            val = (val << 6) | INV[c];
            pos += 6;

            while (pos > 7) {
                baos.write(val >> (pos -= 8));
                val &= ((1 << pos) - 1);
            }
        }
        return baos.toByteArray();
    }

    private Base62() {
    }
}
